home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python151_Src.lha / Python1.5_Source / Modules / ARexxmodule.c < prev    next >
C/C++ Source or Header  |  1999-01-06  |  22KB  |  962 lines

  1.  
  2. /********************************************************************
  3.  
  4.     Lowlevel Amiga ARexx module.
  5.  
  6.     Provides `arexxport' object, which is a opened ARexx port.
  7.     The port returns `arexxmsg' objects.
  8.  
  9. -----------------------------------------------
  10.     (c) 1996-1999 Irmen de Jong.
  11.  
  12.     History:
  13.  
  14.     20-may-96  Created. ARexx functions adapted from code generated by
  15.                ARexxBox, ©Michael Balzer.
  16.     25-may-96  Major overhaul; now uses arexxmsg objects.
  17.     27-may-96  Added ReadArgs function.
  18.      8-jun-96  Rewrote ReadArgs.
  19.      9-jun-96  Moved ReadArgs to doslibmodule.
  20.     26-aug-96  Added message.getvar().
  21.     18-jan-98  Changed for Python 1.5
  22.     12-nov-98  Changed 'arexxll' to 'ARexxll' and 'arexx.error' to 'ARexx.error'
  23.     13-dec-98  Fixed message check code. Changed some comments.
  24.      3-jan-99  Added option to toggle message format (port.setstringmsgs).
  25.                Added option to toggle tokenizing the command line (port.settokenizeline).
  26.  
  27. Module members:
  28.  
  29.     error       -- Exeption string object.  ('ARexx.error')
  30.     port        -- function returning a new ARexx port object.
  31.                    port = ARexxll.port('PORTNAME')
  32.     errorstring -- returns string associated with arexx error code.
  33.  
  34. ARexxPort object members:
  35.  
  36.     name        -- attribute, name of the port (RO)
  37.     signal      -- attribute, signal mask of the MsgPort's sigbit (RO)
  38.     close       -- function, closes the port
  39.     wait        -- function, waits for message to arrive
  40.     getmsg      -- function, returns ARexxMessage object, or None.
  41.     send        -- function, to send command to other port
  42.                    send(to,cmd,async?)    returns (rc,rc2,result) if synchronous.
  43.     setstringmsgs   -- function, toggle message format (1:STRINGS/UNPARSED or 0:PARSED)
  44.     settokenizeline -- function, toggle tokenizing (1:TOKENIZE CMD LINE, 0:DON'T TOKENIZE)
  45.  
  46. ARexxMessage object members:
  47.  
  48.     reply       -- function, replies the message with the given results
  49.                    Each message must be replied to!
  50.     setvar      -- function, sets ARexx variable
  51.     getvar      -- function, extracts ARexx variable
  52.     wantresult  -- attribute, does the message require a result string? (BOOL, RO)
  53.     msg         -- attribute, the message itself (string) (RO)
  54.     rc          -- attribute, result code for reply() (integer)
  55.     rc2         -- attribute, secondary result code (string or None)
  56.     result      -- attribute, result string (string or None)
  57.  
  58.  
  59. **************************************************************************/
  60.  
  61. #include <stdlib.h>
  62. #include <dos.h>
  63. #include <exec/types.h>
  64. #include <exec/memory.h>
  65. #include <dos/dos.h>
  66. #include <exec/libraries.h>
  67. #include <rexx/storage.h>
  68. #include <rexx/rxslib.h>
  69. #include <proto/dos.h>
  70. #include <proto/exec.h>
  71. #include <proto/rexxsyslib.h>
  72. #include <clib/alib_protos.h>
  73. #include "Python.h"
  74.  
  75. #define RHF_CMDSHELL     (1L << 0)
  76. #define RHF_USRMSGPORT   (1L << 1)
  77. #define RHF_NOTPUBLIC    (1L << 2)
  78. #define RHF_STRINGMSGS   (1L << 3)
  79. #define RHF_TOKENIZELINE (1L << 4)
  80.  
  81. #define toupper(c) (c&(~32))
  82.  
  83. struct RexxHost
  84. {
  85.     struct MsgPort *port;
  86.     char portname[ 80 ];
  87.     long replies;
  88.     long flags;
  89.     APTR userdata;      /* Not used yet */
  90. };
  91.  
  92. typedef struct {
  93.     PyObject_HEAD
  94.     struct RexxHost *host;
  95.     ULONG signal;
  96. } arexxportobject;
  97.  
  98. typedef struct {
  99.     PyObject_HEAD
  100.     struct RexxMsg *msg;
  101.     BOOL replied;           // has this message been replied to yet?
  102.     int rc;                 // primary return code (RC -- int)
  103.     PyObject *rc2;          // secondary return code (RC2 -- string)
  104.     PyObject *result;       // RESULT string
  105. } arexxmsgobject;
  106.  
  107.  
  108. struct ExecBase *AbsExecBase;
  109.  
  110. static PyObject *error;    // Exception
  111.  
  112. /* Prototypes for functions defined in arexxmodule.c */
  113.  
  114. struct RexxMsg *CreateRexxCommand( struct RexxHost *host, char *buff, BPTR fh );
  115. static void ReplyRexxCommand( struct RexxMsg *rxmsg, long prim, long sec, char *res );
  116. static void FreeRexxCommand( struct RexxMsg *rxmsg );
  117. static void CloseDownARexxHost( struct RexxHost *host );
  118. static struct RexxHost *SetupARexxHost( char *basename);
  119. static struct RexxMsg *GetARexxMsg( struct RexxHost *host );
  120. struct RexxMsg *SendRexxCommandToPort( struct RexxHost *host,
  121.         char *port, char *cmd, BPTR fh );
  122.  
  123. static BOOL Test_Open(arexxportobject * );
  124. static BOOL Test_Replied(arexxmsgobject * );
  125. static PyObject * port_close(arexxportobject * , PyObject * );
  126. static PyObject * port_wait(arexxportobject * , PyObject * );
  127. static PyObject * port_getmsg(arexxportobject * , PyObject * );
  128. static void port_dealloc(arexxportobject * );
  129. static PyObject * port_getattr(arexxportobject * , unsigned char * );
  130. static PyObject * port_repr(arexxportobject * );
  131. static PyObject * newarexxportobject(unsigned char * );
  132. static void msg_dealloc(arexxmsgobject * );
  133. static PyObject * msg_getattr(arexxmsgobject * , unsigned char * );
  134. static PyObject * msg_repr(arexxmsgobject * );
  135. static PyObject * newarexxmsgobject(struct RexxMsg * );
  136. static PyObject * ARexx_openport(PyObject * , PyObject * );
  137.  
  138. static PyTypeObject ARexxMsgtype;   // fwd
  139.  
  140. #define isARexxMsgObject(ob) ((ob)->ob_type == &ARexxMsgtype)
  141.  
  142.  
  143. ///*** AREXXPORT OBJECT MEMBER FUNCTIONS ***/
  144.  
  145. static BOOL Test_Open(arexxportobject *ao)
  146. {
  147.     if(ao->host && ao->host->port) return TRUE;
  148.     PyErr_SetString(error,"closed port");
  149.     return FALSE;
  150. }
  151.  
  152. static PyObject *port_close(arexxportobject *ao, PyObject *args)
  153. {
  154.     if(!PyArg_NoArgs(args)) return NULL;
  155.  
  156.     if(ao->host) CloseDownARexxHost(ao->host);
  157.     ao->host=NULL;
  158.     Py_INCREF(Py_None);
  159.     return Py_None;
  160. }
  161.  
  162. static PyObject *port_wait(arexxportobject *ao, PyObject *args)
  163. {
  164.     if(!PyArg_NoArgs(args)) return NULL;
  165.  
  166.     if(Test_Open(ao))
  167.     {
  168.         ULONG sigs = Wait(ao->signal | SIGBREAKF_CTRL_C);   /* XXX Abort with ^C */
  169.         if(sigs & SIGBREAKF_CTRL_C)
  170.         {
  171.             PyErr_SetNone(PyExc_KeyboardInterrupt);
  172.             return NULL;
  173.         }
  174.  
  175.         Py_INCREF(Py_None);
  176.         return Py_None;
  177.     } else return NULL;
  178. }
  179.  
  180. static PyObject *port_getmsg(arexxportobject *ao, PyObject *args)
  181. {
  182.     if(!PyArg_NoArgs(args)) return NULL;
  183.  
  184.     if(Test_Open(ao))
  185.     {
  186.         struct RexxMsg *msg;
  187.  
  188.         if(msg=GetARexxMsg(ao->host))
  189.         {
  190.             return newarexxmsgobject(msg);
  191.         }
  192.  
  193.         Py_INCREF(Py_None);
  194.         return Py_None;
  195.     } else return NULL;
  196. }
  197.  
  198. static PyObject *port_send(arexxportobject *ao, PyObject *args)
  199. {
  200.     char *to;
  201.     char *cmd;
  202.     long async;
  203.  
  204.     if(!PyArg_ParseTuple(args,"ssi",&to,&cmd,&async)) return NULL;
  205.  
  206.     if(Test_Open(ao))
  207.     {
  208.         struct RexxMsg *sentrm;     /* the RexxMsg sent to the port */
  209.  
  210.         /* create a new RexxMsg from the command string and send it */
  211.         if( !(sentrm = SendRexxCommandToPort(ao->host, to, cmd,NULL)))
  212.         {
  213.             PyErr_SetString(error,"can't send to port");
  214.             return NULL;
  215.         }
  216.  
  217.         if(!async)
  218.         {
  219.             /* wait for the reply */
  220.             PyObject *reso = NULL;
  221.             long rc;
  222.             struct RexxMsg *rm;
  223.             BOOL waiting = TRUE;
  224.             
  225.             do
  226.             {
  227.                 WaitPort( ao->host->port );
  228.                     
  229.                 while( rm = (struct RexxMsg *) GetMsg(ao->host->port) )
  230.                 {
  231.                     /* Reply? */
  232.                     if( rm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  233.                     {
  234.                         /* 'our' Msg? */
  235.                         if( rm == sentrm )
  236.                         {
  237.                             rc = rm->rm_Result1;
  238.                                 
  239.                             if( !rc && rm->rm_Result2 )
  240.                             {
  241.                                 /* Res2 is String */
  242.                                 reso = Py_BuildValue("(iss)",rc,NULL,rm->rm_Result2);
  243.                             }
  244.                             else
  245.                             {
  246.                                 /* Res2 is number */
  247.                                 reso = Py_BuildValue("(iis)",rc,rm->rm_Result2,NULL);
  248.                             }
  249.  
  250.                             waiting = FALSE;
  251.                         }
  252.                             
  253.                         FreeRexxCommand( rm );
  254.  
  255.                         --ao->host->replies;
  256.                     }
  257.                         
  258.                     /* it's a command, error */
  259.                     else if( ARG0(rm) )
  260.                     {
  261.                         ReplyRexxCommand( rm, -20, (long)
  262.                             "invalid port", NULL );
  263.                     }
  264.                 }
  265.             }
  266.             while( waiting );
  267.  
  268.             return reso;
  269.         }
  270.         else
  271.         {
  272.             Py_INCREF(Py_None);
  273.             return Py_None;
  274.         }
  275.     } else return NULL;
  276. }
  277.  
  278.  
  279. static PyObject *port_setstringmsgs(arexxportobject *ao, PyObject *args)
  280. {
  281.     int i;
  282.     if(!PyArg_ParseTuple(args,"i",&i)) return NULL;
  283.  
  284.     if(i==0)  ao->host->flags &= ~RHF_STRINGMSGS;
  285.     else      ao->host->flags |=  RHF_STRINGMSGS;
  286.  
  287.     Py_INCREF(Py_None);
  288.     return Py_None;
  289. }
  290.  
  291. static PyObject *port_settokenizeline(arexxportobject *ao, PyObject *args)
  292. {
  293.     int i;
  294.     if(!PyArg_ParseTuple(args,"i",&i)) return NULL;
  295.  
  296.     if(i==0)  ao->host->flags &= ~RHF_TOKENIZELINE;
  297.     else      ao->host->flags |=  RHF_TOKENIZELINE;
  298.  
  299.     Py_INCREF(Py_None);
  300.     return Py_None;
  301. }
  302.  
  303. static struct PyMethodDef port_methods[] = {
  304.     {"close", (PyCFunction)port_close, 0},
  305.     {"getmsg", (PyCFunction)port_getmsg, 0},
  306.     {"wait", (PyCFunction)port_wait, 0},
  307.     {"send", (PyCFunction)port_send, 1},
  308.     {"setstringmsgs", (PyCFunction)port_setstringmsgs, 1 },
  309.     {"settokenizeline", (PyCFunction)port_settokenizeline, 1 },
  310.     {NULL,      NULL}       /* sentinel */
  311. };
  312.  
  313.  
  314. static void
  315. port_dealloc(arexxportobject *self)         // `destructor'
  316. {
  317.     if(self->host) CloseDownARexxHost(self->host);
  318.     PyMem_DEL(self);
  319. }
  320.  
  321. static PyObject *
  322. port_getattr(arexxportobject *ao, char *name)
  323. {
  324.     if(ao->host)
  325.     {
  326.         if (strcmp(name, "name")==0)
  327.         {
  328.             if(ao->host->flags & RHF_NOTPUBLIC)
  329.             {
  330.                 // A non-public port doesn't have a name!
  331.                 PyErr_SetString(PyExc_AttributeError,name); return NULL;
  332.             }   
  333.             return PyString_FromString(ao->host->portname);
  334.         }
  335.         else if(strcmp(name,"signal")==0)
  336.             return PyInt_FromLong(ao->signal);
  337.     }
  338.     return Py_FindMethod(port_methods, (PyObject *)ao, name);
  339. }
  340.  
  341. static PyObject *
  342. port_repr(arexxportobject *ao)
  343. {
  344.     char buf[200];
  345.     char *w;
  346.  
  347.     if(!(ao->host))
  348.         w="(closed)";
  349.     else if(ao->host->flags & RHF_NOTPUBLIC)
  350.         w="(private)";
  351.     else
  352.         w=ao->host->portname;
  353.     sprintf(buf,"<arexx port %s at %lx>",w,(long)ao);
  354.     return PyString_FromString(buf);
  355. }
  356.  
  357. static PyTypeObject ARexxPorttype = {
  358.     PyObject_HEAD_INIT(&PyType_Type)
  359.     0,          /*ob_size*/
  360.     "arexxport",        /*tp_name*/
  361.     sizeof(arexxportobject),    /*tp_size*/
  362.     0,          /*tp_itemsize*/
  363.     /* methods */
  364.     (destructor)port_dealloc, /*tp_dealloc*/
  365.     0,          /*tp_print*/
  366.     (getattrfunc)port_getattr, /*tp_getattr*/
  367.     (setattrfunc)0, /*tp_setattr*/
  368.     0,          /*tp_compare*/
  369.     (reprfunc)port_repr,        /*tp_repr*/
  370. };
  371.  
  372.  
  373. static PyObject *
  374. newarexxportobject(char *name)              // `constructor'
  375. {
  376.     arexxportobject *ao;
  377.  
  378.     if(name)
  379.     {
  380.         if(strlen(name)<2)
  381.         {
  382.             PyErr_SetString(PyExc_ValueError,"port name too short");
  383.             return NULL;
  384.         }
  385.  
  386.         (void)strupr(name);
  387.     }
  388.  
  389.     if(ao = PyObject_NEW(arexxportobject, &ARexxPorttype))
  390.     {
  391.         if(ao->host=SetupARexxHost(name))
  392.         {
  393.             ao->signal = 1<<ao->host->port->mp_SigBit;
  394.             return (PyObject*)ao;
  395.         }
  396.         else PyErr_SetString(error,"can't open port");
  397.  
  398.         PyMem_DEL(ao); ao=NULL;
  399.     }
  400.     return (PyObject*)ao;
  401. }
  402.  
  403.  
  404. ///
  405.  
  406. ///*** AREXXMSG OBJECT MEMBER FUNCTIONS ***/
  407.  
  408. static BOOL Test_Replied(arexxmsgobject *am)
  409. {
  410.     if(am->replied)
  411.     {
  412.         PyErr_SetString(error,"already replied");
  413.         return FALSE;
  414.     }
  415.     return TRUE;
  416. }
  417.  
  418. static PyObject *msg_reply(arexxmsgobject *am, PyObject *args)
  419. {
  420.     if(!PyArg_NoArgs(args)) return NULL;
  421.  
  422.     if(Test_Replied(am))
  423.     {
  424.         char *rc2, *result;
  425.  
  426.         rc2 = PyString_Check(am->rc2)? PyString_AsString(am->rc2) : NULL;
  427.         result = PyString_Check(am->result)? PyString_AsString(am->result) : NULL;
  428.  
  429.         am->rc = -am->rc;       // for ReplyRexxCommand; 'rc2 is string'
  430.         ReplyRexxCommand(am->msg,am->rc,(long)rc2,result);
  431.         am->replied=TRUE;
  432.  
  433.         Py_INCREF(Py_None);
  434.         return Py_None;
  435.     } else return NULL;
  436. }
  437.  
  438. static PyObject *msg_setvar(arexxmsgobject *am, PyObject *args)
  439. {
  440.     char *name, *val;
  441.     int vlen;
  442.     if(!PyArg_ParseTuple(args,"ss#",&name,&val,&vlen)) return NULL;
  443.  
  444.     if(Test_Replied(am))
  445.     {
  446.         if(CheckRexxMsg((struct Message*)am->msg))
  447.         {
  448.             if(0==SetRexxVar((struct Message*)am->msg,name,val,vlen))
  449.             {
  450.                 Py_INCREF(Py_None);
  451.                 return Py_None;
  452.             }
  453.         }
  454.         PyErr_SetString(error,"can't set var - invalid message?");
  455.     }
  456.     return NULL;
  457. }
  458.  
  459. static PyObject *msg_getvar(arexxmsgobject *am, PyObject *args)
  460. {
  461.     char *name, *val;
  462.     if(!PyArg_ParseTuple(args,"s",&name)) return NULL;
  463.  
  464.     if(Test_Replied(am))
  465.     {
  466.         if(CheckRexxMsg((struct Message*)am->msg))
  467.         {
  468.             if(0==GetRexxVar((struct Message*)am->msg,name,&val))
  469.             {
  470.                 if(val!=NULL) return PyString_FromString(val);
  471.             }
  472.         }
  473.         PyErr_SetString(error,"can't get var - invalid message?");
  474.     }
  475.     return NULL;
  476. }
  477.  
  478. static struct PyMethodDef msg_methods[] = {
  479.     {"reply", (PyCFunction) msg_reply, 0},
  480.     {"setvar", (PyCFunction) msg_setvar, 1},
  481.     {"getvar", (PyCFunction) msg_getvar, 1},
  482.     {NULL,      NULL}       /* sentinel */
  483. };
  484.  
  485. static void
  486. msg_dealloc(arexxmsgobject *am)         // `destructor'
  487. {   
  488.     if(!am->replied)
  489.     {
  490.         char *rc2, *result;
  491.  
  492.         rc2 = PyString_Check(am->rc2)? PyString_AsString(am->rc2) : NULL;
  493.         result = PyString_Check(am->result)? PyString_AsString(am->result) : NULL;
  494.  
  495.         am->rc = -am->rc;       // for ReplyRexxCommand; 'rc2 is string'
  496.         ReplyRexxCommand(am->msg,am->rc,(long)rc2,result);
  497.     }
  498.     Py_DECREF(am->rc2);
  499.     Py_DECREF(am->result);
  500.  
  501.     /* Do NOT delete the msg structure itself; we've got it from someone else! */
  502.  
  503.     PyMem_DEL(am);
  504. }
  505.  
  506.  
  507. static PyObject *
  508. msg_getattr(arexxmsgobject *am, char *name)
  509. {
  510.     if (strcmp(name, "msg")==0)
  511.         return PyString_FromString(ARG0(am->msg));
  512.     if (strcmp(name, "rc")==0)
  513.         return PyInt_FromLong(am->rc);
  514.     if (strcmp(name, "rc2")==0)
  515.     {
  516.         Py_INCREF(am->rc2);
  517.         return am->rc2;
  518.     }
  519.     if (strcmp(name, "result")==0)
  520.     {
  521.         Py_INCREF(am->result);
  522.         return am->result;
  523.     }
  524.     if (strcmp(name, "wantresult")==0)
  525.     {
  526.         if( am->msg->rm_Action & RXFF_RESULT )
  527.             return PyInt_FromLong(1);
  528.         else
  529.             return PyInt_FromLong(0);
  530.     }
  531.  
  532.     return Py_FindMethod(msg_methods, (PyObject *)am, name);
  533. }
  534.  
  535. static int
  536. msg_setattr(arexxmsgobject *am, char *name, PyObject *args)
  537. {
  538.     if(args==NULL)
  539.     {
  540.         PyErr_SetString(PyExc_AttributeError,"can't delete msg attrs"); return -1;
  541.     }
  542.  
  543.     if (strcmp(name, "rc")==0)
  544.     {
  545.         if(PyInt_Check(args))
  546.         {
  547.             long rc = PyInt_AsLong(args);
  548.             if(rc>=0)
  549.             {
  550.                 am->rc=rc;
  551.             }
  552.             else
  553.             {
  554.                 PyErr_SetString(PyExc_ValueError,"rc must be >=0"); return -1;
  555.             }
  556.         }
  557.         else
  558.         {
  559.             PyErr_SetString(PyExc_TypeError,"expecting int arg"); return -1;
  560.         }
  561.     }
  562.     else if (strcmp(name, "rc2")==0)
  563.     {
  564.         if(PyString_Check(args))
  565.         {
  566.             Py_DECREF(am->rc2);
  567.             Py_INCREF(args);
  568.             am->rc2 = args;
  569.         }
  570.         else
  571.         {
  572.             PyErr_SetString(PyExc_TypeError,"expecting string arg"); return -1;
  573.         }
  574.     }
  575.     else if (strcmp(name, "result")==0)
  576.     {
  577.         if(PyString_Check(args))
  578.         {
  579.             Py_DECREF(am->result);
  580.             Py_INCREF(args);
  581.             am->result = args;
  582.         }
  583.         else
  584.         {
  585.             PyErr_SetString(PyExc_TypeError,"expecting string arg"); return -1;
  586.         }
  587.     }
  588.     else
  589.     {
  590.         PyErr_SetString(PyExc_AttributeError,name); return -1;
  591.     }
  592.  
  593.     return 0;
  594. }
  595.  
  596. static PyObject *
  597. msg_repr(arexxmsgobject *am)
  598. {
  599.     char buf[100];
  600.     sprintf(buf, "<arexx msg at %lx>", (long)am);
  601.     return PyString_FromString(buf);
  602. }
  603.  
  604. static PyTypeObject ARexxMsgtype = {
  605.     PyObject_HEAD_INIT(&PyType_Type)
  606.     0,          /*ob_size*/
  607.     "arexxmsg",        /*tp_name*/
  608.     sizeof(arexxmsgobject),    /*tp_size*/
  609.     0,          /*tp_itemsize*/
  610.     /* methods */
  611.     (destructor)msg_dealloc, /*tp_dealloc*/
  612.     0,          /*tp_print*/
  613.     (getattrfunc)msg_getattr, /*tp_getattr*/
  614.     (setattrfunc)msg_setattr, /*tp_setattr*/
  615.     0,          /*tp_compare*/
  616.     (reprfunc)msg_repr,        /*tp_repr*/
  617. };
  618.  
  619. static PyObject *
  620. newarexxmsgobject(struct RexxMsg *msg)             // `constructor'
  621. {
  622.     arexxmsgobject *am;
  623.  
  624.     if(am = PyObject_NEW(arexxmsgobject, &ARexxMsgtype))
  625.     {
  626.         am->msg=msg;
  627.         am->rc=0;
  628.         Py_INCREF(Py_None); am->rc2=Py_None;
  629.         Py_INCREF(Py_None); am->result=Py_None;
  630.         am->replied=FALSE;
  631.     }
  632.     return (PyObject*)am;
  633. }
  634.  
  635.  
  636. ///
  637.  
  638. ///******************************* AREXX SUPPORT FUNCTIONS *******************/
  639.  
  640. struct RexxMsg *CreateRexxCommand( struct RexxHost *host, char *buff, BPTR fh )
  641. {
  642.     struct RexxMsg *rexx_command_message;
  643.  
  644.     if( (rexx_command_message = CreateRexxMsg( host->port,
  645.         "python", host->port->mp_Node.ln_Name)) == NULL )
  646.     {
  647.         return( NULL );
  648.     }
  649.  
  650.     if( (rexx_command_message->rm_Args[0] =
  651.         CreateArgstring(buff,strlen(buff))) == NULL )
  652.     {
  653.         DeleteRexxMsg(rexx_command_message);
  654.         return( NULL );
  655.     }
  656.  
  657.     rexx_command_message->rm_Action = RXCOMM | RXFF_RESULT;
  658.     rexx_command_message->rm_Stdin  = fh;
  659.     rexx_command_message->rm_Stdout = fh;
  660.  
  661.     if(host->flags & RHF_STRINGMSGS)
  662.         rexx_command_message->rm_Action |= RXFF_STRING;
  663.     if(host->flags & RHF_TOKENIZELINE)
  664.         rexx_command_message->rm_Action |= RXFF_TOKEN;
  665.  
  666.     return( rexx_command_message );
  667. }
  668.  
  669.  
  670. static void ReplyRexxCommand(
  671.     struct RexxMsg  *rexxmessage,
  672.     long            primary,
  673.     long            secondary,
  674.     char            *result )
  675. {
  676.     if( rexxmessage->rm_Action & RXFF_RESULT )
  677.     {
  678.         if( primary == 0 )
  679.         {
  680.             secondary = result
  681.                 ? (long) CreateArgstring( result, strlen(result) )
  682.                 : (long) NULL;
  683.         }
  684.         else
  685.         {
  686.             char buf[16];
  687.             
  688.             if( primary > 0 )
  689.             {
  690.                 sprintf( buf, "%ld", secondary );
  691.                 result = buf;
  692.             }
  693.             else
  694.             {
  695.                 primary = -primary;
  696.                 result = (char *) secondary;
  697.             }
  698.  
  699.             if(CheckRexxMsg((struct Message*)rexxmessage))
  700.             {
  701.                 SetRexxVar( (struct Message *) rexxmessage,
  702.                     "RC2", result, strlen(result) );
  703.             }
  704.  
  705.             secondary = 0;
  706.         }
  707.     }
  708.     else if( primary < 0 )
  709.         primary = -primary;
  710.     
  711.     rexxmessage->rm_Result1 = primary;
  712.     rexxmessage->rm_Result2 = secondary;
  713.     ReplyMsg( (struct Message *) rexxmessage );
  714. }
  715.  
  716. static void FreeRexxCommand( struct RexxMsg *rexxmessage )
  717. {
  718.     if( !rexxmessage->rm_Result1 && rexxmessage->rm_Result2 )
  719.         DeleteArgstring( (char *) rexxmessage->rm_Result2 );
  720.  
  721.     if( rexxmessage->rm_Stdin &&
  722.         rexxmessage->rm_Stdin != Input() )
  723.         Close( rexxmessage->rm_Stdin );
  724.  
  725.     if( rexxmessage->rm_Stdout &&
  726.         rexxmessage->rm_Stdout != rexxmessage->rm_Stdin &&
  727.         rexxmessage->rm_Stdout != Output() )
  728.         Close( rexxmessage->rm_Stdout );
  729.  
  730.     DeleteArgstring( (char *) ARG0(rexxmessage) );
  731.     DeleteRexxMsg( rexxmessage );
  732. }
  733.  
  734.  
  735. static void CloseDownARexxHost( struct RexxHost *host )
  736. {
  737.     struct RexxMsg *rexxmsg;
  738.     
  739.     if( host->port )
  740.     {
  741.         /* Remove port */
  742.         if(!(host->flags & RHF_NOTPUBLIC))
  743.             RemPort( host->port );
  744.         
  745.         /* Wait for pending replies */
  746.         while( host->replies > 0 )
  747.         {
  748.             WaitPort( host->port );
  749.             
  750.             while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  751.             {
  752.                 if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  753.                 {
  754.                     FreeRexxCommand( rexxmsg );
  755.                     --host->replies;
  756.                 }
  757.                 else
  758.                     ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  759.             }
  760.         }
  761.         
  762.         /* flush the MsgPort */
  763.         while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  764.             ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  765.         
  766. //        if( !(host->flags & RHF_USRMSGPORT) )
  767.             DeleteMsgPort( host->port );
  768.     }
  769.     
  770.     free( host );
  771. }
  772.  
  773. // static struct RexxHost *SetupARexxHost( char *basename, struct MsgPort *usrport )
  774. static struct RexxHost *SetupARexxHost( char *basename)
  775. {
  776.     struct RexxHost *host;
  777.     int ext = 0;
  778.     
  779.     if( !(host = calloc(sizeof *host, 1)) )
  780.         return NULL;
  781.  
  782.     if(basename) strcpy( host->portname, basename );
  783.     else host->flags |= RHF_NOTPUBLIC;
  784.  
  785.     if( !(host->port = CreateMsgPort()) )
  786.     {
  787.         free( host );
  788.         return NULL;
  789.     }
  790.     else
  791.     {
  792.         host->port->mp_Node.ln_Pri = 0;
  793.     }
  794.     
  795.  
  796.     if(!(host->flags & RHF_NOTPUBLIC))
  797.     {
  798.         Forbid();
  799.         while( FindPort(host->portname) )
  800.             sprintf( host->portname, "%s.%d", basename, ++ext );
  801.  
  802.         host->port->mp_Node.ln_Name = host->portname;
  803.         AddPort( host->port );
  804.  
  805.         Permit();
  806.     }
  807.  
  808.     /* default flags */
  809.     // host->flags |= RHF_STRINGMSGS;
  810.     // host->flags |= RHF_TOKENIZELINE;
  811.  
  812.     return( host );
  813. }
  814.  
  815. /* GetARexxMsg:
  816. ** returns the RexxMsg that is waiting at the port, 
  817. ** or NULL if no message is present. 
  818. */
  819. static struct RexxMsg *GetARexxMsg( struct RexxHost *host )
  820. {
  821.     struct RexxMsg *rexxmsg;
  822.  
  823.     while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  824.     {
  825.         if( (rexxmsg->rm_Action & RXCODEMASK) != RXCOMM )
  826.         {
  827.             /* Not a Rexx-Message */
  828.             ReplyMsg( (struct Message *) rexxmsg );
  829.         }
  830.         else if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  831.         {
  832.             struct RexxMsg *org = (struct RexxMsg *) rexxmsg->rm_Args[15];
  833.             
  834.             if( org )
  835.             {
  836.                 /* Reply through the message */
  837.                 if( rexxmsg->rm_Result1 != 0 )
  838.                 {
  839.                     /* Command unknown */
  840.                     ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  841.                 }
  842.                 else
  843.                 {
  844.                     ReplyRexxCommand( org, 0, 0, (char *) rexxmsg->rm_Result2 );
  845.                 }
  846.             }
  847.  
  848.             FreeRexxCommand( rexxmsg );
  849.             --host->replies;
  850.         }
  851.         else if( ARG0(rexxmsg) )
  852.         {
  853.             return rexxmsg;     /* return the ARexx message! */
  854.         }
  855.         else
  856.         {
  857.             ReplyMsg( (struct Message *) rexxmsg );
  858.         }
  859.     }
  860.  
  861.     return NULL;    /* no important message arrived. */
  862. }
  863.  
  864.  
  865. struct RexxMsg *SendRexxCommandToPort( struct RexxHost *host, char *port, char *cmd, BPTR fh )
  866. {
  867.     struct RexxMsg *rcm;
  868.     
  869.     if( rcm = CreateRexxCommand(host, cmd, fh) )
  870.     {
  871.         struct MsgPort *rexxport;
  872.     
  873.         Forbid();
  874.  
  875.         if( (rexxport = FindPort(port)) == NULL )
  876.         {
  877.             Permit();
  878.             return( NULL );
  879.         }
  880.  
  881.         PutMsg( rexxport, &rcm->rm_Node );
  882.     
  883.         Permit();
  884.     
  885.         ++host->replies;
  886.         return( rcm );
  887.     }
  888.     else
  889.         return NULL;
  890. }
  891.  
  892. ///
  893.  
  894. ///******************************** MODULE FUNCTIONS ************************/
  895.  
  896. static PyObject *
  897. ARexx_openport(PyObject *self, PyObject *args)
  898. {
  899.     PyObject *p=NULL;
  900.     
  901.     if (!PyArg_ParseTuple(args, "|O", &p))
  902.         return NULL;
  903.  
  904.     if(!p)
  905.         return newarexxportobject("PYTHON");
  906.     else if(p==Py_None)
  907.         /* open anonymous port (only for sending) */
  908.         return newarexxportobject(NULL);
  909.     else if(PyString_Check(p))
  910.         return newarexxportobject(PyString_AsString(p));
  911.     else
  912.         return (PyObject*)PyErr_BadArgument();
  913. }
  914.  
  915. static PyObject *
  916. ARexx_errorstring(PyObject *self, PyObject *args)
  917. {
  918. /* undocumented function: */
  919. extern BOOL ErrorMsg(LONG err);
  920. #pragma libcall RexxSysBase ErrorMsg 60 001 
  921.  
  922.     long err;
  923.     if (!PyArg_ParseTuple(args, "i", &err))
  924.         return NULL;
  925.  
  926.     if(ErrorMsg(err))
  927.     {
  928.         struct NexxStr *s = (struct NexxStr*)getreg(REG_A0);
  929.         return PyString_FromStringAndSize(&s->ns_Buff[0],s->ns_Length);
  930.     }
  931.     else
  932.     {
  933.         PyErr_SetString(PyExc_ValueError,"invalid error code");
  934.         return NULL;
  935.     }
  936. }
  937.  
  938.  
  939. /*** FUNCTIONS FROM THE MODULE ***/
  940.  
  941. static struct PyMethodDef ARexx_global_methods[] = {
  942.     {"port",  ARexx_openport, 1},
  943.     {"errorstring", ARexx_errorstring, 1},
  944.     {NULL,      NULL}       /* sentinel */
  945. };
  946. ///
  947.  
  948. void
  949. initARexx Py_PROTO((void))
  950. {
  951.     PyObject *m, *d;
  952.         AbsExecBase = *(struct ExecBase**)4;
  953.  
  954.     m = Py_InitModule("ARexxll", ARexx_global_methods);
  955.     d = PyModule_GetDict(m);
  956.  
  957.     /* Initialize error exception */
  958.     error = PyErr_NewException("ARexx.error", NULL, NULL);
  959.     if (error != NULL)
  960.         PyDict_SetItemString(d, "error", error);
  961. }
  962.